Skip to content

feat(renderer): randomize star field seeds#22

Merged
kunchenguid merged 9 commits intomainfrom
feat/randomize-stars
Apr 3, 2026
Merged

feat(renderer): randomize star field seeds#22
kunchenguid merged 9 commits intomainfrom
feat/randomize-stars

Conversation

@kunchenguid
Copy link
Copy Markdown
Owner

Summary

This change makes the renderer's star field feel unique per run by generating per-instance seeds instead of reusing fixed ones. It also hardens the terminal layout pipeline so wide Unicode graphemes, emoji, and full-width characters wrap, measure, and clamp correctly without breaking centered content or side-star alignment.

Risk Assessment: 🟡 Medium — Tests are strong, but a known correctness gap remains in the new width heuristic on a core rendering path.

Architecture

flowchart TD
  subgraph renderer_flow["Renderer Flow"]
    direction TB
    renderer_cls["Renderer (updated)"]
    session_seeds["Session Star Seeds (updated)"]
    star_gen["generateStarField (unchanged)"]
    frame_builder["buildFrameCells (updated)"]
    terminal_frame["Terminal Frame Output (unchanged)"]

    renderer_cls -->|"creates once"| session_seeds
    session_seeds -->|"seed top/bottom/side fields"| star_gen
    renderer_cls -->|"rebuilds frame"| frame_builder
    star_gen -->|"provides star positions"| frame_builder
    frame_builder -->|"renders centered scene"| terminal_frame
  end

  subgraph text_layout["Unicode Layout Support"]
    direction TB
    terminal_width["terminal-width utils (added)"]
    word_wrap["wordWrap (updated)"]
    cell_encoder["Cell Encoding in renderer-diff (updated)"]
    width_clamp["Cell Width Clamp (updated)"]

    terminal_width -->|"measures grapheme display width"| word_wrap
    terminal_width -->|"sets per-cell widths"| cell_encoder
    word_wrap -->|"supplies wrapped prompt/message lines"| frame_builder
    cell_encoder -->|"supplies cell arrays"| frame_builder
    width_clamp -->|"prevents content overflow"| frame_builder
  end
Loading

Key changes made

  • Renderer now creates stable random seeds for the top, bottom, and side star fields once per instance, then reuses them across renders and resizes.
  • Added terminal-width utilities built on Intl.Segmenter to split graphemes and compute display width for combining marks, full-width glyphs, and emoji.
  • Updated wordWrap, renderer-diff, and frame centering to use grapheme-aware widths, preserve wide glyphs at line boundaries, and avoid overflowing the 63-column content area.
  • Expanded tests to cover randomized star seeding, wide-character wrapping, grapheme width calculation, and frame-width alignment invariants.

How was this tested

  • Full test suite passed and an additional CLI smoke test with a wide-glyph boundary case behaved correctly.
  • Validated the renderer/grapheme-width change by running npm test, which builds the project and runs the full Vitest suite. Result: 27 test files passed, 249 tests passed, including the new renderer, word-wrap, terminal-width, and existing e2e coverage. I also ran a manual CLI smoke test against the built binary with a boundary-case prompt of 62 As plus 🌕; it exited with code 0 and the captured terminal output showed the wide glyph wrapped onto its own line rather than being dropped or merged incorrectly.

Critique Comments

  • 🔴 src/utils/terminal-width.ts:52 - Using Extended_Pictographic as a blanket 2-column signal misclassifies plain text symbols like ©, , , , and as wide even without emoji presentation. That makes prompts/messages wrap and truncate a column early; restrict the fast-path to actual emoji presentation sequences (VS16/ZWJ/keycap/flags) or East Asian wide code points.

@kunchenguid kunchenguid merged commit e658f32 into main Apr 3, 2026
3 checks passed
@kunchenguid kunchenguid deleted the feat/randomize-stars branch April 3, 2026 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant